/* 
 *	Copyright (C) 2009-2010 miaohua
 *	http://code.google.com/p/lrcshower/
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#include "StdAfx.h"
#include <Windows.h>
#include <Streams.h>
#include <string>
#include "ConstDef.h"
#include "AppMsgDef.h"
#include "SettingHdr.h"
#include "LrcShowFilter.h"
#include "RegOptHelper.h"
#include "HelperFunctions.h"
#include "Resource.h"
#include "SearchLrcDlg.h"
#include "WinLrcShowDlg.h"
#include "DeskLrcShowDlg.h"
#include "PlayListDlg.h"
#include "SimpleFileDownloader.h"
#include "MusicBoxSetting.h"


// Static variable definition
long MusicBoxSetting::VOLUME_FULL     = 0L;
long MusicBoxSetting::VOLUME_SILENCE  = -5000L;

MusicBoxSetting::MusicBoxSetting()
:m_WinProp(Reg_WinPath)
,m_DeskProp(Reg_DeskPath)
,m_LrcProp(Reg_LrcPath)
{
     // Initialize COM
     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

     // Read value from window's register
     if( !DeserializeFromReg() )
         SetDefaultVal();

     // Set lrc desktop show's default position and size
     m_LrcDeskDefaultRect.left = GetSystemMetrics(SM_CXSCREEN)/8;
     m_LrcDeskDefaultRect.top = GetSystemMetrics(SM_CYSCREEN)*3/5;
     m_LrcDeskDefaultRect.right = GetSystemMetrics(SM_CXSCREEN)*7/8;
     m_LrcDeskDefaultRect.bottom = GetSystemMetrics(SM_CYSCREEN)*3/5+120;

     // Initialization lrc show filter
     m_LrcShowFilter.CreateLrcFilter();
     m_LrcShowFilter.InitLrcFilter(*this);
}

MusicBoxSetting::~MusicBoxSetting()
{
     // Save value to window's register     
     SerializeToReg();

     // Release COM
     CoUninitialize();
}

bool MusicBoxSetting::SerializeToReg()
{
     // Reg location
	 const TCHAR * Path = Reg_PlayerPath;
	 // Open the reg key
	 DWORD Disp = REG_OPENED_EXISTING_KEY;
	 HKEY PlayerKey;
     if( RegCreateKeyEx(HKEY_LOCAL_MACHINE, Path, 0, NULL, REG_OPTION_NON_VOLATILE,
         KEY_WRITE, NULL, &PlayerKey, &Disp) !=ERROR_SUCCESS )
         return false;

     // Put key to realse helper
     RegKeyReleaseHelper AutoReleasePlayerKey(PlayerKey);
     
     // Save play mode value
     SaveRegDWORDVal(PlayerKey, _T("PlayMode"), m_PlayMode, return false);

     // Save show mode value
     SaveRegDWORDVal(PlayerKey, _T("ShowMode"), m_ShowMode, return false);

     // Save selected play list index
     SaveRegDWORDVal(PlayerKey, _T("SelPlayListIdx"), m_SelPlayListIdx, return false);

     // Save volume value
     SaveRegDWORDVal(PlayerKey, _T("Volume"), m_Volume, return false);

     // Save wether is mute
     SaveRegDWORDVal(PlayerKey, _T("Mute"), m_Mute, return false);

     // Save wether is recursed
     SaveRegDWORDVal(PlayerKey, _T("FolderRecurse"), m_IsRecurse, return false);

     // Save lrc show window's position and size
     SaveRegDWORDVal(PlayerKey, _T("LrcWinLeft"), m_LrcShowWinRect.left, return false);
     SaveRegDWORDVal(PlayerKey, _T("LrcWinTop"), m_LrcShowWinRect.top, return false);
     SaveRegDWORDVal(PlayerKey, _T("LrcWinRight"), m_LrcShowWinRect.right, return false);
     SaveRegDWORDVal(PlayerKey, _T("LrcWinBottom"), m_LrcShowWinRect.bottom, return false);

     SaveRegDWORDVal(PlayerKey, _T("LrcDeskLeft"), m_LrcShowDeskRect.left, return false);
     SaveRegDWORDVal(PlayerKey, _T("LrcDeskTop"), m_LrcShowDeskRect.top, return false);
     SaveRegDWORDVal(PlayerKey, _T("LrcDeskRight"), m_LrcShowDeskRect.right, return false);
     SaveRegDWORDVal(PlayerKey, _T("LrcDeskBottom"), m_LrcShowDeskRect.bottom, return false);
     
     // Save playlist window's position and size
     SaveRegDWORDVal(PlayerKey, _T("PLDlgLeft"), m_PLDlgRect.left, return false);
     SaveRegDWORDVal(PlayerKey, _T("PLDlgTop"), m_PLDlgRect.top, return false);
     SaveRegDWORDVal(PlayerKey, _T("PLDlgRight"), m_PLDlgRect.right, return false);
     SaveRegDWORDVal(PlayerKey, _T("PLDlgBottom"), m_PLDlgRect.bottom, return false);
     
     // Save playlist
     SerializePLToReg(PlayerKey);

     // Save reg key values
     RegFlushKey(PlayerKey);

     return true;
}

bool MusicBoxSetting::SerializePLToReg(HKEY PlayerKey)
{
     // Create playlist sub key
     HKEY PLKey;
	 DWORD Disp = REG_OPENED_EXISTING_KEY;
     if( RegCreateKeyEx(PlayerKey, PlayList_Reg_KeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
         KEY_WRITE, NULL, &PLKey, &Disp) !=ERROR_SUCCESS )
         return false;

     // Put key to auto-realse helper
     RegKeyReleaseHelper AutoReleasePLKey(PLKey);
    
     int Size = m_PlayList.size();
     int PLCounter = 0;
     // Save every playlist
     for( int i = 0; i < Size; ++i )
     { 
          // Check wether it is invalidate
          if( !m_PlayList[i].IsValidate() )
              continue;

          // <<PlayList>>+(0,1,2,...) is the key name for every play list
          tstring KeyName = OnePL_Reg_KeyName_Prefix + IntToStr(PLCounter);
          // Create sub key for one play list
          HKEY OnePL;
          if( RegCreateKeyEx(PLKey, KeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE,
              KEY_WRITE, NULL, &OnePL, &Disp) !=ERROR_SUCCESS )
              continue;

          // Put key to auto-realse helper
          RegKeyReleaseHelper AutoReleaseOnePLKey(OnePL);

          // Count playlist number
          ++PLCounter;

          // Save current playlist' name
          SaveRegSZVal(OnePL, OnePL_Reg_Name, m_PlayList[i].m_PLName);
          // Save current selected song's index
          SaveRegDWORDVal(OnePL, OnePL_Reg_SongIdxName, m_PlayList[i].GetSelSongIdx(), continue);

          int OnePLSize = m_PlayList[i].Size();
          int SongCounter = 0;
          for( int j = 0; j < OnePLSize; ++j )
          {
               // Check wether the song has been deleted
               if( !m_PlayList[i].m_SongList[j].IsValidate() )
                   continue;
               // <<Song>>+(0,1,2,...) is the key name for every song in current play list
               tstring KeyName = OneSong_Reg_KeyName_Prefix + IntToStr(SongCounter);
               // Create sub key for one song
               HKEY OneSong;
               if( RegCreateKeyEx(OnePL, KeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE,
                   KEY_WRITE, NULL, &OneSong, &Disp) !=ERROR_SUCCESS )
                   continue;
               // Put key to auto-realse helper
               RegKeyReleaseHelper AutoReleaseOneSongKey(OneSong);
    
               // Count song number
               ++SongCounter;

               // Save name of current song
               SaveRegSZVal(OneSong, OneSong_Reg_SongName, m_PlayList[i].m_SongList[j].m_Song);
               // Save singer of current song
               SaveRegSZVal(OneSong, OneSong_Reg_SingerName, m_PlayList[i].m_SongList[j].m_Singer);
               // Save full path of current song
               SaveRegSZVal(OneSong, OneSong_Reg_PathName, m_PlayList[i].m_SongList[j].m_FullPath);
          }
          // Save current playlist' size
          SaveRegDWORDVal(OnePL, OnePL_Reg_SizeName, SongCounter, continue);
     }
     // Save playlists size
     SaveRegDWORDVal(PLKey, PlayList_Reg_SizeName, PLCounter, return false);

     return true;
}

bool MusicBoxSetting::DeserializeFromReg()
{
     // Open the reg key
     HKEY PlayerKey;
     if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, Reg_PlayerPath, 0, KEY_READ, &PlayerKey) !=ERROR_SUCCESS )
	     return false;

     // Put key to realse helper
     RegKeyReleaseHelper AutoReleasePlayerKey(PlayerKey);

     // Get play mode value
     DWORD Holder = 0;
     QueryRegDWORDVal(PlayerKey, _T("PlayMode"), Holder, return false);
     m_PlayMode = (PlayMode)Holder;

     // Get show mode value
     QueryRegDWORDVal(PlayerKey, _T("ShowMode"), Holder, return false);
     m_ShowMode = (ShowMode)Holder;

     // Get selected play list index
     QueryRegDWORDVal(PlayerKey, _T("SelPlayListIdx"), m_SelPlayListIdx, return false);

     // Get volume value
     QueryRegDWORDVal(PlayerKey, _T("Volume"), m_Volume, return false);

     // Get wether is mute
     QueryRegBoolVal(PlayerKey, _T("Mute"), m_Mute, return false);

     // Get wether is recursed
     QueryRegBoolVal(PlayerKey, _T("FolderRecurse"), m_IsRecurse, return false);

     // Get lrc show window's position and size
     QueryRegDWORDVal(PlayerKey, _T("LrcWinLeft"), m_LrcShowWinRect.left, return false);
     QueryRegDWORDVal(PlayerKey, _T("LrcWinTop"), m_LrcShowWinRect.top,return false);
     QueryRegDWORDVal(PlayerKey, _T("LrcWinRight"), m_LrcShowWinRect.right,return false);
     QueryRegDWORDVal(PlayerKey, _T("LrcWinBottom"), m_LrcShowWinRect.bottom,return false);

     QueryRegDWORDVal(PlayerKey, _T("LrcDeskLeft"), m_LrcShowDeskRect.left,return false);
     QueryRegDWORDVal(PlayerKey, _T("LrcDeskTop"), m_LrcShowDeskRect.top,return false);
     QueryRegDWORDVal(PlayerKey, _T("LrcDeskRight"), m_LrcShowDeskRect.right,return false);
     QueryRegDWORDVal(PlayerKey, _T("LrcDeskBottom"), m_LrcShowDeskRect.bottom,return false);

     // Get playlist window's postion and size
     QueryRegDWORDVal(PlayerKey, _T("PLDlgLeft"), m_PLDlgRect.left,return false);
     QueryRegDWORDVal(PlayerKey, _T("PLDlgTop"), m_PLDlgRect.top,return false);
     QueryRegDWORDVal(PlayerKey, _T("PLDlgRight"), m_PLDlgRect.right,return false);
     QueryRegDWORDVal(PlayerKey, _T("PLDlgBottom"), m_PLDlgRect.bottom,return false);

     // Get playlists
     DeserializePLFromReg(PlayerKey);

     return true;
}


bool MusicBoxSetting::DeserializePLFromReg(HKEY PlayerKey)
{
     // Open playlist sub key
     HKEY PLKey;
     if( RegOpenKeyEx(PlayerKey, PlayList_Reg_KeyName, 0, KEY_READ, &PLKey) !=ERROR_SUCCESS )
	     return false;

     // Put key to auto-realse helper
     RegKeyReleaseHelper AutoReleasePLKey(PLKey);
     
     // Get size of playlists
     DWORD PLSize = 0;
     QueryRegDWORDVal(PLKey, PlayList_Reg_SizeName, PLSize, return false);
     m_PlayList.reserve(PLSize);

     // Get every play list
     for( DWORD i = 0; i < PLSize; ++i )
     {
          // <<PlayList>>+(0,1,2,...) is the key name for every play list
          tstring KeyName = OnePL_Reg_KeyName_Prefix + IntToStr(i);

          // Open playlist sub key
          HKEY OnePL;
          if( RegOpenKeyEx(PLKey, KeyName.c_str(), 0, KEY_READ, &OnePL) !=ERROR_SUCCESS )
	          continue;
           
          // Put key to auto-realse helper
          RegKeyReleaseHelper AutoReleaseOnePLKey(OnePL);

          OnePlayList PlayList;
          // Get current playlist' name
          QueryRegSZVal(OnePL, OnePL_Reg_Name, PlayList.m_PLName);
          // Get selected song's index
          QueryRegDWORDVal(OnePL, OnePL_Reg_SongIdxName, PlayList.m_SelSongIdx, continue);

          // Get current playlist' size
          DWORD PLSize = 0;
          QueryRegDWORDVal(OnePL, OnePL_Reg_SizeName, PLSize, continue);
          PlayList.m_SongList.reserve(PLSize);
          
          // Get song one by one
          for( DWORD j = 0; j < PLSize; ++j )
          {
               // <<Song>>+(0,1,2,...) is the key name for every song in current play list
               tstring KeyName = OneSong_Reg_KeyName_Prefix + IntToStr(j);
               // Open sub key for one song
               HKEY OneSongKey;
               if( RegOpenKeyEx(OnePL, KeyName.c_str(), 0, KEY_READ, &OneSongKey) !=ERROR_SUCCESS )
                   continue;
               // Put key to auto-realse helper
               RegKeyReleaseHelper AutoReleaseOneSongKey(OneSongKey);
               
               SongProp Song;
               
               // Position in play list
               Song.m_Index = j;
               // Initialize property index of current song to be zero
               Song.m_PropIndex = 0;
               // Get name of current song
               QueryRegSZVal(OneSongKey, OneSong_Reg_SongName, Song.m_Song);
               // Get singer of current song
               QueryRegSZVal(OneSongKey, OneSong_Reg_SingerName, Song.m_Singer);
               // Get full path of current song
               QueryRegSZVal(OneSongKey, OneSong_Reg_PathName, Song.m_FullPath);
               // Get to current playlist
               PlayList.m_SongList.push_back(Song);
          }

          // Save current playlist
          m_PlayList.push_back(PlayList);
          // Generate random index 
          m_PlayList.back().GenRandIdx();
     }
  
     return true;     
}

void MusicBoxSetting::SetDefaultVal()
{
     m_PlayMode = SEQ;
     m_SelPlayListIdx = 0;
     m_Volume = VOLUME_SILENCE/4;
     m_Mute = false;
     m_IsRecurse = false;

     memset(&m_LrcShowWinRect, 0, sizeof(m_LrcShowWinRect));
     memset(&m_LrcShowDeskRect, 0, sizeof(m_LrcShowDeskRect)); 
     memset(&m_PLDlgRect, 0, sizeof(m_PLDlgRect));

     // Set default playlist
     OnePlayList PL;
     PL.m_PLName = Def_PL_Name;
     m_PlayList.push_back(PL);
}


void MusicBoxSetting::ChangeShowMode()
{
     ILrcShowFilter * FilterInterface = NULL;
     HRESULT HR = m_LrcShowFilter->QueryInterface(IID_ILrcShowFilter, (void **)&FilterInterface);
     if( HR == S_OK )
     {
         if( m_ShowMode == WinMode )
         {
             // Record current window lrc show's size
             GetWindowRect(m_WinLrcShowDlg->m_hWnd, &m_LrcShowWinRect);
             // If we haven't get dektop lrc show window, just set default position
             if( m_LrcShowDeskRect.bottom == 0 )
                 m_DeskLrcShowDlg->MoveWindow(&m_LrcDeskDefaultRect);
             else
                 // Restore the orignal position
                 m_DeskLrcShowDlg->MoveWindow(&m_LrcShowDeskRect);
             // Change to desktop lrc show
             FilterInterface->SetDeskShowWnd(m_DeskLrcShowDlg->m_hWnd);
             FilterInterface->SetDeskLrcFile(m_LrcFullPath.c_str());
             FilterInterface->ChgToDeskShow();
             m_DeskLrcShowDlg->ShowWindow(SW_SHOW);
             m_WinLrcShowDlg->ShowWindow(SW_HIDE);
             m_ShowMode = DeskMode;
         } else {
             // Record current desktop lrc show's size
             GetWindowRect(m_DeskLrcShowDlg->m_hWnd, &m_LrcShowDeskRect);
             // If we haven't get lrc desktop show's position, just set default position
             if( m_LrcShowWinRect.bottom == 0 )
                 m_WinLrcShowDlg->MoveWindow(&m_LrcWinDefaultRect);
             else
                 // Restore the orignal position
                 m_WinLrcShowDlg->MoveWindow(&m_LrcShowWinRect);
             // Change to window lrc show
             FilterInterface->SetWinShowWnd(m_WinLrcShowDlg->m_hWnd);
             FilterInterface->SetWinLrcFile(m_LrcFullPath.c_str());
             FilterInterface->ChgToWinShow();
             m_DeskLrcShowDlg->ShowWindow(SW_HIDE);
             m_WinLrcShowDlg->ShowWindow(SW_SHOW);
             m_ShowMode = WinMode;
         }
         FilterInterface->Release();
     }
}

bool MusicBoxSetting::DoLrcSearch(unsigned int SongIdx, unsigned int PLIdx)
{
     // Use default m_SelPlayListIdx
     if( PLIdx == -1 )
         PLIdx = m_SelPlayListIdx;
     // Check value range of Index
     if( PLIdx >= m_PlayList.size() )
         return false;
     if( SongIdx >= m_PlayList[PLIdx].Size() )
         return false;

     // Do lrc file search(local or online)
     // If no lrc file can be found, show search lrc by usr prompt
     if( !DoLrcSearch(m_PlayList[PLIdx].m_SongList[SongIdx]) )
     {
         m_WinLrcShowDlg->ShowSearchLrcPrompt();
         InvalidateLrcWin();
         return false;
     } else
         m_WinLrcShowDlg->HideSearchLrcPrompt();
     
     return true;
}

bool MusicBoxSetting::DoLrcSearch(const SongProp & Song)
{
     // Firstly, do local search(register & folders)
     tstring LrcFullPath;
     if( DoLocalLrcSearch(Song.m_FullPath, LrcFullPath) )
     {
         m_LrcFullPath = LrcFullPath;
         return true;
     }
     
     // Secondly, do online search(if user checks the auto-online-search box
     if( m_LrcProp.m_AutoSearch && DoOnlineLrcSearch(Song.m_Song, Song.m_Singer) )
     {
         if( m_LrcProp.m_LrcList.size() > 1 && m_LrcProp.m_PromptMulti )
         {
             CSearchLrcDlg SearchDlg;
             SearchDlg.DoModal();
             return true;
         } else {
             // Get first one url 
             tstring LrcUrl;
             if( !m_LrcProp.GetLrcDownloadUrl(0, LrcUrl) ) 
                 return false;
         
             // Download    
             LrcFullPath = m_LrcProp.m_FolderPath + _T("\\") + Song.GetLabel() + _T(".lrc");
             CSimpleFileDownloader FileLoader;
             if( FileLoader.StartFileDownload(LrcUrl, LrcFullPath) )
             {
                 m_LrcFullPath = LrcFullPath;
                 SongProp::SetAssignedLrcFile(Song.m_FullPath, LrcFullPath);
                 return true;
             }
         
             return false;
         }
     }

     return false;     
}

bool MusicBoxSetting::DoLocalLrcSearch(const tstring & SongFullPath, tstring & LrcFullPath)
{
     // First search register, just look for 
     // current song's accosiated lrc file's path
     if( !SongProp::GetAssignedLrcFile(SongFullPath, LrcFullPath) )
         return false;
 
     // If first step is unable to get, just do local search

     return IsFileExist(LrcFullPath);
}

bool MusicBoxSetting::DoOnlineLrcSearch(const tstring & Song, const tstring & Singer)
{
     if( Song.empty() ) return false;

     // Do online search
     tstring ErrMsg;
     int EngineIdx = m_LrcProp.m_SearchEngineIdx;
     if( m_LrcProp.m_SearchEngineAPI[EngineIdx].SearchLrc(
                            Song, 
                            Singer, 
                            ErrMsg, 
                            m_LrcProp.m_LrcList, 0) <= 0 )
         return false;

     return true;
}

int MusicBoxSetting::AddOneSong(const tstring & SongFullPath, int PLIdx, int Pos)
{
    if( PLIdx == -1 )
        return AddOneSongHelper(SongFullPath, m_SelPlayListIdx, Pos);
    else
        return AddOneSongHelper(SongFullPath, PLIdx, Pos);
}

int MusicBoxSetting::AddOneSongHelper(const tstring & SongFullPath, int PLIdx, int Pos)
{
     int Index = m_PlayList[PLIdx].AddOneSong(SongFullPath, Pos);

     // Notify play list dialog which play list has added new one
     m_PLDlg->PostMessage(WM_PL_ADDONE, PLIdx, 0);

     return Index;
}

int MusicBoxSetting::MoveOneSong(int SrcIdx, int DstIdx, int PLIdx)
{
    return m_PlayList[PLIdx].MoveOneSong(SrcIdx, DstIdx);
}

bool MusicBoxSetting::DelOnePL(unsigned int PLIdx)
{
     if( PLIdx >= m_PlayList.size() )
         return false;

     HKEY PLKey;
     if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, Reg_PLPath, 0, KEY_READ, &PLKey) !=ERROR_SUCCESS )
	     return false;

     // Put key to auto-realse helper
     RegKeyReleaseHelper AutoReleaseOnePLKey(PLKey);

     // Delete it
     // <<PlayList>>+(0,1,2,...) is the key name for every play list
     tstring KeyName = OnePL_Reg_KeyName_Prefix + IntToStr(PLIdx);
     if( RegDeleteKey(PLKey, KeyName.c_str()) != ERROR_SUCCESS )
         return false; 

     // Save reg key values
     RegFlushKey(PLKey);

     // Remove from play lists(just invalidate the playlist)
     m_PlayList[PLIdx].Invalidate();
     
     return true;
}

int MusicBoxSetting::AddOnePL(const tstring & PLName)
{
     OnePlayList PL;
     PL.m_PLName = PLName;
     m_PlayList.push_back(PL);
     return m_PlayList.size()-1; 
}

bool MusicBoxSetting::DelOneSong(unsigned int SongIdx, unsigned int PLIdx)
{
     if( PLIdx >= m_PlayList.size() )
         return false;
     if( SongIdx >= m_PlayList[PLIdx].m_SongList.size() )
         return false;

     // Clear Register record
     tstring PL = OnePL_Reg_KeyName_Prefix + IntToStr(PLIdx);
     tstring Path = Reg_PLPath;
     Path = Path + _T("\\") + PL;

     HKEY PLKey;
     LONG Res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Path.c_str(), 0, KEY_READ, &PLKey);
     // Not find the key & not success
     if( Res == ERROR_FILE_NOT_FOUND ) 
         return true;
     if( Res != ERROR_SUCCESS )
         return false; 

     // Put key to auto-realse helper
     RegKeyReleaseHelper AutoReleaseOnePLKey(PLKey);

     // Delete it
     // <<Song>>+(0,1,2,...) is the key name for every song in current play list
     tstring KeyName = OneSong_Reg_KeyName_Prefix + IntToStr(SongIdx);
     Res = RegDeleteKey(PLKey, KeyName.c_str());
     // Not find the key & not success
     if( Res != ERROR_FILE_NOT_FOUND && Res != ERROR_SUCCESS )
         return false; 

     // Remove from play list
     m_PlayList[PLIdx].m_SongList[SongIdx].Invalidate();
   
     return true;     
}

bool MusicBoxSetting::DelAllSong(unsigned int PLIdx)
{
     if( PLIdx >= m_PlayList.size() )
         return false;

     unsigned int Size = m_PlayList[PLIdx].Size();
     for( unsigned int i = 0; i < Size; ++i )
          DelOneSong(i, PLIdx);

     return true;
}

int MusicBoxSetting::GetPrevSongIdx(unsigned int PLIdx)
{
    if( PLIdx == -1 ) PLIdx = m_SelPlayListIdx;
    if( PLIdx >= m_PlayList.size() ) return -1;
  
    return m_PlayList[m_SelPlayListIdx].GetPrevSongIdx(m_PlayMode);
}

int MusicBoxSetting::GetNextSongIdx(unsigned int PLIdx)
{
    if( PLIdx == -1 ) PLIdx = m_SelPlayListIdx;
    if( PLIdx >= m_PlayList.size() ) return -1;
  
    return m_PlayList[m_SelPlayListIdx].GetNextSongIdx(m_PlayMode);
}


bool MusicBoxSetting::OpenOneSong(unsigned int SongIdx, unsigned int PLIdx)
{
     // Use default m_SelPlayListIdx
     if( PLIdx == -1 )
         PLIdx = m_SelPlayListIdx;
     // Check value range of Index
     if( PLIdx >= m_PlayList.size() )
         return false;
     if( SongIdx >= m_PlayList[PLIdx].Size() )
         return false;

     // Set current song's index
     m_PlayList[PLIdx].SetSelSongIdx(SongIdx);
     // Set current playing play list index
     m_SelPlayListIdx = PLIdx;
     // Set current song's full path
     m_SongFullPath = m_PlayList[PLIdx].GetFullPath();
     // Clear previous song's lrc full path
     m_LrcFullPath.clear();
     // Stop lrc show filter if needed
     m_LrcShowFilter.StopLrcFilter(*this);

     return true;     
}



void MusicBoxSetting::InvalidateLrcWin()
{
     m_WinLrcShowDlg->Invalidate();
     m_WinLrcShowDlg->UpdateWindow();
}

void MusicBoxSetting::ShowLrcDlg(HWND ParentHwnd)
{
     // Show the lrc dialog in the right position
     if( m_ShowMode == WinMode )
     {
         if( m_WinLrcShowDlg->IsWindowVisible() )
         {
             m_WinLrcShowDlg->ShowWindow(SW_HIDE);
             m_WinLrcShowDlg->GetWindowRect(&m_LrcShowWinRect);
         } else {
             if( m_LrcShowWinRect.bottom == 0 )
             {
                 CRect Child, Parent;
                 m_WinLrcShowDlg->GetWindowRect(&Child);
                 GetWindowRect(ParentHwnd, &Parent);
                 m_LrcWinDefaultRect.left = Parent.right;
                 m_LrcWinDefaultRect.top = Parent.top;
                 m_LrcWinDefaultRect.right = Parent.right+Child.Width();
                 m_LrcWinDefaultRect.bottom = Parent.top+Child.Height();
                 m_WinLrcShowDlg->MoveWindow(&m_LrcWinDefaultRect);
             } else 
                 m_WinLrcShowDlg->MoveWindow(&m_LrcShowWinRect);
             m_WinLrcShowDlg->ShowWindow(SW_SHOW);
         }
     } else {
         if( m_DeskLrcShowDlg->IsWindowVisible() )
         {
             m_DeskLrcShowDlg->ShowWindow(SW_HIDE);
             m_DeskLrcShowDlg->GetWindowRect(&m_LrcShowDeskRect);
         } else {
             if( m_LrcShowDeskRect.bottom == 0 )
                 m_DeskLrcShowDlg->MoveWindow(&m_LrcDeskDefaultRect);
             else
                 m_DeskLrcShowDlg->MoveWindow(&m_LrcShowDeskRect);
             m_DeskLrcShowDlg->ShowWindow(SW_SHOW);
         }
     }
}


void MusicBoxSetting::ShowPLDlg(HWND ParentHwnd)
{
     // Show or hide
     if( m_PLDlg->IsWindowVisible() )
     {
         // Hide window
         m_PLDlg->ShowWindow(SW_HIDE);
         // Record pl dialog position
         m_PLDlg->GetWindowRect(&m_PLDlgRect);
     } else {
         // Show play list dialog in the right position
         if( m_PLDlgRect.bottom == 0 )
         {
             CRect Child, Parent;
             m_PLDlg->GetWindowRect(&Child);
             GetWindowRect(ParentHwnd, &Parent);
             m_PLDlg->MoveWindow(Parent.left, Parent.bottom, Child.Width(), Child.Height());
         }else
             m_PLDlg->MoveWindow(&m_PLDlgRect);
         // Show window
         m_PLDlg->ShowWindow(SW_SHOW);
     }
}

void MusicBoxSetting::NotifyPLDlg(int SongIdx)
{
     // Notice we must *Get position index* to send it to play list dialog
     // Position index indicates the real position in song play list
     m_PLDlg->SendMessage(WM_PL_CURPLAY, m_PlayList[m_SelPlayListIdx].GetIndex(SongIdx), 0);
}

REFERENCE_TIME MusicBoxSetting::GetSongDura(int SongIdx, int PLIdx)const
{
     if( PLIdx == -1 )
         return GetDuraHelper(SongIdx, m_SelPlayListIdx);
     else 
         return GetDuraHelper(SongIdx, PLIdx);
}

REFERENCE_TIME MusicBoxSetting::GetDuraHelper(int SongIdx, int PLIdx)const
{
     if( PLIdx < 0 || PLIdx >= m_PlayList.size() )
         return 0;

     return m_PlayList[PLIdx].GetDura(SongIdx);
}

tstring MusicBoxSetting::GetSongNextProp(int SongIdx, int PLIdx)
{
     if( PLIdx == -1 )
         return GetNextPropHelper(SongIdx, m_SelPlayListIdx);
     else
         return GetNextPropHelper(SongIdx, PLIdx);  
}

tstring MusicBoxSetting::GetNextPropHelper(int SongIdx, int PLIdx)
{
     if( PLIdx < 0 || PLIdx >= m_PlayList.size() )
         return _T("");

     return m_PlayList[PLIdx].GetNextProp(SongIdx);
}

tstring MusicBoxSetting::GetSongLabel(int SongIdx, int PLIdx)const
{
     if( PLIdx == -1 )
         return GetLabelHelper(SongIdx, m_SelPlayListIdx);
     else
         return GetLabelHelper(SongIdx, PLIdx);
}

tstring MusicBoxSetting::GetLabelHelper(int SongIdx, int PLIdx)const
{
     if( PLIdx < 0 || PLIdx >= m_PlayList.size() )
         return _T("");

     return m_PlayList[PLIdx].GetLabel(SongIdx);
}

tstring MusicBoxSetting::GetSongFullPath(int SongIdx, int PLIdx)const
{
     if( PLIdx == -1 )
         return GetFullPathHelper(SongIdx, m_SelPlayListIdx);
     else
         return GetFullPathHelper(SongIdx, PLIdx);

}
     
tstring MusicBoxSetting::GetFullPathHelper(int SongIdx, int PLIdx)const
{
     if( PLIdx < 0 || PLIdx >= m_PlayList.size() )
         return _T("");

     return m_PlayList[PLIdx].GetFullPath(SongIdx);
}

tstring MusicBoxSetting::GetSongName(int SongIdx, int PLIdx)const
{
     if( PLIdx == -1 )
         return GetNameHelper(SongIdx, m_SelPlayListIdx);
     else
         return GetNameHelper(SongIdx, PLIdx);
}
     
tstring MusicBoxSetting::GetNameHelper(int SongIdx, int PLIdx)const
{
     if( PLIdx < 0 || PLIdx >= m_PlayList.size() )
         return _T("");

     return m_PlayList[PLIdx].GetSongName(SongIdx);
}

tstring MusicBoxSetting::GetSingerName(int SongIdx, int PLIdx)const
{
     if( PLIdx == -1 )
         return GetSingerHelper(SongIdx, m_SelPlayListIdx);
     else
         return GetSingerHelper(SongIdx, PLIdx);
}

tstring MusicBoxSetting::GetSingerHelper(int SongIdx, int PLIdx)const
{
     if( PLIdx < 0 || PLIdx >= m_PlayList.size() )
         return _T("");

     return m_PlayList[PLIdx].GetSingerName(SongIdx);
}

bool MusicBoxSetting::GetPLSongProp(unsigned int PLIdx)
{  
     if( PLIdx == -1 ) PLIdx = m_SelPlayListIdx;
     if( PLIdx >= m_PlayList.size() ) return false;
     
     // Read song prop
     m_PlayList[PLIdx].GetSongProp();
     
     return true;
}

tstring MusicBoxSetting::GetSongTips(unsigned int SongIdx, unsigned int PLIdx)
{
     if( PLIdx == -1 ) PLIdx = m_SelPlayListIdx;
     if( PLIdx >= m_PlayList.size() ) return false;
     
     // Read song prop
     return m_PlayList[PLIdx].GetSongTips(SongIdx);
}

void MusicBoxSetting::ReloadWinLrc()
{
     m_LrcShowFilter.ReloadWinLrc(m_LrcFullPath);
}

void MusicBoxSetting::ReloadDeskLrc()
{
     m_LrcShowFilter.ReloadDeskLrc(m_LrcFullPath);
}

bool MusicBoxSetting::LoadAssignedLrc(const tstring & LrcFullPath)
{
     m_LrcFullPath = LrcFullPath;
     // Start lrc show filter
     if( !m_LrcShowFilter.StartLrcFilter(*this) )
         return false;

     return true;     
}

bool MusicBoxSetting::StartLrcShow()
{
     // Start lrc show filter
     if( !m_LrcShowFilter.StartLrcFilter(*this) )
         return false;
     
     return true;
}


long MusicBoxSetting::GetSilenceVol()
{
     return VOLUME_SILENCE;
}

long MusicBoxSetting::GetVolume()
{
     return m_Volume;
}

void MusicBoxSetting::SetVolume(long Vol)
{
     m_Volume = Vol;
}

bool MusicBoxSetting::IsMute()
{
     return m_Mute;
}

void MusicBoxSetting::SetMute(bool Mute)
{
     m_Mute = Mute;
}

tstring MusicBoxSetting::GetCurSongFullPath()const
{
    return m_SongFullPath;
}

tstring MusicBoxSetting::GetCurLrcFullPath()const
{
     return m_LrcFullPath;
}

int MusicBoxSetting::GetSelPLIdx()const
{
     return m_SelPlayListIdx;
}

bool MusicBoxSetting::GetRecurse()const
{
     return m_IsRecurse;
}

void MusicBoxSetting::SetRecurse(bool IsRecurse)
{
     m_IsRecurse = IsRecurse;
}

ShowMode MusicBoxSetting::GetShowMode()const
{
     return m_ShowMode;
}

int MusicBoxSetting::GetPlayMode()const
{
     return m_PlayMode;
}

void MusicBoxSetting::SetPlayMode(int Mode)
{
     m_PlayMode = Mode;
}